﻿(function ($) {
    function createAutocompleteSource(request, response, options, defaultOption) {

        var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
        response((function () {

            var requestTerm = request.term,
                requestIsEmpty = (requestTerm === ''),
                matchingOptions;

            matchingOptions = options.map(function () {
                var text = this.text,
                    isDefaultOption = this.value === defaultOption.value;

                if (this.value && (!isDefaultOption || requestIsEmpty) && (!requestTerm || matcher.test(text))) {
                    return {
                        label: text.replace(
                            new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(requestTerm) + ")(?![^<>]*>)(?![^&;]+;)", "gi"),
                            "<strong>$1</strong>"
                        ),
                        value: text,
                        option: this
                    };
                }

                return null;
            });

            // display the default option if no matching options found
            if (matchingOptions.length === 0) {

                matchingOptions.push({
                    label: defaultOption.text,
                    value: defaultOption.text,
                    option: defaultOption
                });
            }

            return matchingOptions;
        } ()));
    }

    $.widget("ui.combobox", {
        _create: function () {
            var input,
				that = this,
				select = this.element.hide(),
                options = select.children('option'),
                defaultOption = options[0],
				selected = select.children(":selected"),
				value = selected.val() ? selected.text() : "",
				wrapper = this.wrapper = $("<span>")
					.addClass("ui-combobox")
					.insertAfter(select),
                autocompleteList,
                menu,
                inputAutocomplete,
                itemSelectedByUser;

            function removeIfInvalid(element) {
                var value = $(element).val(),
					matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(value) + "$", "i"),
					valid = false;
                select.children("option").each(function () {
                    if ($(this).text().match(matcher)) {
                        this.selected = valid = true;
                        return false;
                    }
                });
                if (!valid) {
                    // remove invalid value, as it didn't match anything
                    $(element).val(defaultOption.text);
                    select.val(defaultOption.value);
                    input.data("autocomplete").term = "";
                    return false;
                }
            }
            input = that.input = $("<input>")
					.appendTo(wrapper)
					.val(value)
					.attr("title", "")
					.addClass("ui-state-default ui-combobox-input")
					.autocomplete($.extend(that.options, {
					    delay: 0,
					    minLength: 0,
					    autoFocus: true,
					    source: function (request, response) {
					        createAutocompleteSource(request, response, options, defaultOption);
					    },
					    open: function () {
					        var firstMenuItem = menu.element.children().first(),
                                firstMenuItemValue = firstMenuItem.attr('data-value');
					        select.val(firstMenuItemValue);
					        firstMenuItem.trigger("mouseenter");
					    },
					    close: function () {
					        // set text to default if no other option selected
					        if (select.val() === defaultOption.value) {
					            input.val(defaultOption.text);
					        }
					    },
					    select: function (event, ui) {
					        itemSelectedByUser = true;
					        ui.item.option.selected = true;
					        that._trigger("selected", event, {
					            item: ui.item.option
					        });
					    },
					    change: function (event, ui) {
					        if (!ui.item) {
					            var selected = select.children(":selected");
					            if (selected.length > 0) {
					                var inputText = $(this).val();
					                var selectedOptionText = selected.text();
					                if (selectedOptionText.toUpperCase().indexOf(inputText.toUpperCase()) != -1) {
					                    $(this).val(selectedOptionText);
					                }
					            }
					            return removeIfInvalid(this);
					        }
					    },
					    focus: function (event, ui) {
					        ui.item.option.selected = true;
					    }
					}))
					.addClass("ui-widget ui-widget-content ui-corner-left");

            autocompleteList = input.autocomplete('widget');
            // select the first item when the mouse leaves the drop down list
            autocompleteList.bind('mouseleave', function (e) {
                if (!itemSelectedByUser) {
                    e.preventDefault();
                    var firstMenuItem = menu.element.children().first(),
                        firstMenuItemValue = firstMenuItem.attr('data-value');
                    select.val(firstMenuItemValue);
                    firstMenuItem.trigger("mouseenter");
                } else {
                    itemSelectedByUser = false;
                }
            });
            inputAutocomplete = input.data('autocomplete');
            menu = inputAutocomplete.menu;

            input.data("autocomplete")._renderItem = function (ul, item) {
                return $("<li data-value=" + item.option.value + "></li>")
                    .data("item.autocomplete", item)
                    .append("<a>" + item.label + "</a>")
                    .appendTo(ul);
            };

            $("<a>")
					.attr("tabIndex", -1)
					.appendTo(wrapper)
					.button({
					    icons: {
					        primary: "ui-icon-triangle-1-s"
					    },
					    text: false
					})
					.removeClass("ui-corner-all")
					.addClass("ui-corner-right ui-combobox-toggle")
					.click(function () {
					    // close if already visible
					    if (input.autocomplete("widget").is(":visible")) {
					        input.autocomplete("close");
					        removeIfInvalid(input);
					        return;
					    }

					    // work around a bug (likely same cause as #5265)
					    $(this).blur();

					    // pass empty string as value to search for, displaying all results
					    input.autocomplete("search", "");
					    input.focus();
					});

        },

        destroy: function () {
            this.input.autocomplete('widget').unbind('mouseleave');
            this.wrapper.remove();
            this.element.show();
            $.Widget.prototype.destroy.call(this);
        }
    });
})(jQuery);